/**************************************************************
* M3D_VMX.H   Crossplatform VMX support
**************************************************************/
#ifndef _M3D_VMX_H_
#define _M3D_VMX_H_


#include <m3d/m3d_vmx_helpers.h>

#if defined(_AP_PC) || defined(_AP_XENON)

#if defined(_AP_PC)
#include <wtypes.h>
#endif
#if defined(_AP_XENON)
#include <xtl.h>
#endif
#include <./DX_sdk/include/xnamath.h>
#endif

#if defined _AP_PS3

#include <vec_types.h>
#ifdef SPU
#include <vmx2spu.h>
#else
#include <altivec.h>
#endif

#include <vectormath/cpp/vectormath_aos.h>
#include <vectormath/cpp/vectormath_soa.h>
using namespace Vectormath;

//namespace Aos {
// Multiply a 4-D vector by a scalar (scalar data contained in vector data type)
inline const Aos::Vector4 operator *( Aos::Vector4 vec0, Aos::Vector4 vec1 ) { return Aos::mulPerElem(vec0, vec1); }
inline const Aos::Vector4 operator /( Aos::Vector4 vec0, Aos::Vector4 vec1 ) { return Aos::divPerElem(vec0, vec1); }

//} // namespace Aos
#endif





#if defined(_AP_PC) || defined(_AP_XENON)
typedef XMVECTOR vmxV;
typedef XMMATRIX vmxMATR;
#elif defined(_AP_PS3)
typedef Aos::Vector4 vmxV;
typedef Aos::Matrix4R vmxMATR;
#else
#error "Unsupported VMX platform"
#endif 


//
// Vector Load & store
//
__INLINE vmxV vmxVectLoadA      (float *src); 
__INLINE vmxV vmxVectLoadUA     (float *src); 
__INLINE vmxV vmxVectLoad3UA    (float *src); 
__INLINE vmxV vmxVectLoadShort4 (const INT16 *vert); 

__INLINE void vmxVectStoreA     (vmxV v, float *dst); 
__INLINE void vmxVectStoreUA    (vmxV v, float *dst); 
__INLINE void vmxVectStore3UA   (vmxV v, float *dst); 

//
// Integer in vector
//
__INLINE vmxV vmxVectSetInt (int   x, int   y, int   z, int   w);
//__INLINE vmxV vmxVectConvertIntToFloat (vmxV v, int divExp); this function is implemented as a define
//__INLINE vmxV vmxVectConvertfloatToInt (vmxV v, int divExp); this function is implemented as a define

//
// Vector Set & Get
//
__INLINE vmxV vmxVectSet    (float x, float y, float z, float w);
__INLINE vmxV vmxVectSet    (int   x, int   y, int   z, int   w);
__INLINE vmxV vmxVectSetX   (vmxV v, float x);
__INLINE vmxV vmxVectSetY   (vmxV v, float y);
__INLINE vmxV vmxVectSetZ   (vmxV v, float z);
__INLINE vmxV vmxVectSetW   (vmxV v, float w);

__INLINE float vmxVectGetX  (vmxV v);
__INLINE float vmxVectGetY  (vmxV v);
__INLINE float vmxVectGetZ  (vmxV v);
__INLINE float vmxVectGetW  (vmxV v);


//
// Vector Rounding & Conversion
//
__INLINE vmxV vmxVectFloor    (vmxV v);
__INLINE vmxV vmxVectCeiling  (vmxV v); 
__INLINE vmxV vmxVectRound    (vmxV v); 
__INLINE vmxV vmxVectTrunc    (vmxV v); 

//
// Vector Math ops
//
__INLINE vmxV vmxVectAbs      (vmxV v); 
__INLINE vmxV vmxVectNegate   (vmxV a); // -a
__INLINE vmxV vmxVectAdd      (vmxV a, vmxV b); // a+b
__INLINE vmxV vmxVectSub      (vmxV a, vmxV b); // a-b
__INLINE vmxV vmxVectMul      (vmxV a, vmxV b); // a*b
__INLINE vmxV vmxVectDivide   (vmxV a, vmxV b); // a/b
__INLINE vmxV vmxVectMadd     (vmxV a, vmxV b, vmxV c); // a*b+c
__INLINE vmxV vmxVectSqrt     (vmxV v); 
__INLINE vmxV vmxVectSqrtEst  (vmxV v); 
__INLINE vmxV vmxVectRecip    (vmxV v); 
__INLINE vmxV vmxVectRecipEst (vmxV v); 
__INLINE vmxV vmxVectRecipSqrt(vmxV v); 
__INLINE vmxV vmxVectRecipSqrtEst(vmxV v); 
__INLINE vmxV vmxVectDot      (vmxV a, vmxV b); 
__INLINE vmxV vmxVectCross    (vmxV a, vmxV b); 
__INLINE vmxV vmxVectLerp     (vmxV a, vmxV b, vmxV t); // a+t*(b-a)


//
// Vector Comparison
//
__INLINE vmxV vmxVectGreaterOrEqual (vmxV v1, vmxV v2);
__INLINE vmxV vmxVectGreater        (vmxV v1, vmxV v2);
__INLINE vmxV vmxVectLess           (vmxV v1, vmxV v2);
__INLINE vmxV vmxVectSelect         (vmxV v1, vmxV v2, vmxV control);
__INLINE vmxV vmxVectMin            (vmxV v1, vmxV v2);
__INLINE vmxV vmxVectMax            (vmxV v1, vmxV v2);
__INLINE vmxV vmxVectSaturate       (vmxV v);

//
// Vector misc functions
//
__INLINE vmxV vmxVectZero           (void);
__INLINE vmxV vmxVectOne            (void);



//
// Matrix Load & store
//
__INLINE vmxMATR vmxMatrLoadA   (float *src); 
__INLINE vmxMATR vmxMatrLoadUA  (float *src); 

__INLINE void    vmxMatrStoreA  (vmxMATR &m, float *dst); 
__INLINE void    vmxMatrStore3A (vmxMATR &m, float *dst); 
__INLINE void    vmxMatrStoreUA (vmxMATR &m, float *dst); 

//
// Matrix operations
//
__INLINE vmxMATR vmxMatrTranspose (vmxMATR &m); 
__INLINE vmxMATR vmxMatrIdentity  (void); 











// XMVector4NearEqual / vec_all_in
// TransformPoint: XMVector3Transform
// TransformVector: XMVector3TransformNormal
// TransformPointList: XMVector3TransformCoordStream
// TransformVectorList: XMVector3TransformNormalStream
// m3dNormalize
// m3dNormalizeVertList


//
// Implementation
//
#include<m3d/m3d_vmx.hpp>


#endif //_M3D_VMX_H_

//
// End of file 'M3D_VMX.H'
//
